﻿using System;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using BitsOfStuff.Support;

namespace BitsOfStuff
{
    /// <summary>
    /// Class that implement basic datastructure of vector
    /// </summary>
    public struct MyVector
    {
        private MySelectedPoint _startPoint;
        private MySelectedPoint _endPoint;
        private Double _vectorAngle;
        private double _vectorLength;
        private double _normVectorX;
        private double _normVectorY;
        private double _distanceConst;
        private MyPoint _virtualCircleCenter;

        /// <summary>
        /// Gets relative X distance between start and end point
        /// </summary>
        /// <returns>relative Y distance</returns>
        public double getVectorRelativeX()
        {
            return _endPoint.getPoint().getX() - _startPoint.getPoint().getX();
        }

        /// <summary>
        /// Get relative Y distance between start and end point
        /// </summary>
        /// <returns>relative Y distance</returns>
        public double getVectorRelativeY()
        {
            return _endPoint.getPoint().getY() - _startPoint.getPoint().getY();
        }

        /// <summary>
        /// Get vecort length
        /// </summary>
        /// <returns>vector length</returns>
        public double getVectorLength()
        {
            double vectorRelativeX = getVectorRelativeX();

            double vectorRelativeY = getVectorRelativeY();

            var vectorRelativeXSq = (int)Math.Pow(vectorRelativeX, 2);

            var vectorRelativeYSq = (int)Math.Pow(vectorRelativeY, 2);

            var vectorLength = (int)Math.Sqrt(vectorRelativeXSq + vectorRelativeYSq);

            return vectorLength;
        }

        private double _getVectorAngle()
        {
            double vectorRelativeX = getVectorRelativeX();
            double vectorRelativeY = getVectorRelativeY();
            return Math.Atan2(vectorRelativeY, vectorRelativeX);
        }

        /// <summary>
        /// Get vector angle from X axes
        /// </summary>
        /// <returns>vector angle</returns>
        public double getVectorAngle()
        {
            return _vectorAngle * (180 / Math.PI);
        }

        /// <summary>
        /// Conctructor of vector
        /// </summary>
        /// <param name="startPoint">Startpoint of veceotr</param>
        /// <param name="endPoint">Endpoint of vector</param>
        public void makeVector(MySelectedPoint startPoint, MySelectedPoint endPoint)
        {
            _startPoint = startPoint;
            _endPoint = endPoint;
            calculateNormVector();
            _vectorAngle = _getVectorAngle();
            _vectorLength = getVectorLength();
        }

        /// <summary>
        /// Constructor of vector
        /// </summary>
        /// <param name="startPoint">start point</param>
        /// <param name="endPoint">end point</param>
        public void makeVector(MyPoint startPoint, MyPoint endPoint)
        {
            makeVector(new MySelectedPoint(startPoint), new MySelectedPoint(endPoint));
        }

        /*
                private void calculateEndPoint()
                {
                    _endPoint.getPoint().setX((int)(Math.Sin(_vectorAngle) * _vectorLength));
                    _endPoint.getPoint().setX((int)(Math.Cos(_vectorAngle) * _vectorLength));
                }
        */

        /// <summary>
        /// Function that return startPoint of vector
        /// </summary>
        /// <returns>Vector startPoint</returns>
        public MySelectedPoint getStartPoint()
        {
            return _startPoint;
        }

        /// <summary>
        /// Function that returns end point of vector
        /// </summary>
        /// <returns>end point</returns>
        public MySelectedPoint getEndPoint()
        {
            return _endPoint;
        }

        /// <summary>
        /// Function that calculate distance of point from vector
        /// </summary>
        /// <param name="point">Other point</param>
        /// <returns>Distance this point from vector</returns>
        public double distance(MyPoint point)
        {
            double top = Math.Abs((_endPoint.getX() - _startPoint.getX())
                                 * (_startPoint.getY() - point.getY())
                                 - (_startPoint.getX() - point.getX())
                                 * (_endPoint.getY() - _startPoint.getY()));
            double bottom =
                Math.Sqrt(Math.Pow(_endPoint.getX() - _startPoint.getX(), 2) +
                          Math.Pow(_endPoint.getY() - _startPoint.getY(), 2));

            return top / bottom;
        }

        /// <summary>
        /// Calculate distance of stylus point from vector
        /// </summary>
        /// <param name="point">Point</param>
        /// <returns>Distance of stylus point</returns>
        public double distance(StylusPoint point)
        {
            MyPoint _point = new MyPoint();
            _point.create(point);
            return distance(_point);
        }

        private void calculateNormVector()
        {
            _normVectorX = -getVectorRelativeY();
            _normVectorY = getVectorRelativeX();
            _distanceConst = (_normVectorX * _startPoint.getPoint().getX() +
           _normVectorY * _startPoint.getPoint().getY()) * -1;
        }

        /// <summary>
        /// Function that calculate distance of point fron start and end point and drawn that distance
        /// </summary>
        /// <param name="point">Point</param>
        /// <param name="inkCanvas">InkCanvas for drawing</param>
        /// <returns>SemiCyrcle distance</returns>
        public double calculateSemiCyrcleAreaDistance(MyPoint point, InkCanvas inkCanvas)
        {
            double vectorMidleX = getStartPoint().getPoint().getX() + getVectorRelativeX() / 2;
            double vectorMidleY = getStartPoint().getPoint().getY() + getVectorRelativeY() / 2;
            _virtualCircleCenter = new MyPoint();
            _virtualCircleCenter.setX(vectorMidleX + _normVectorX * 2);
            _virtualCircleCenter.setY(vectorMidleY + _normVectorY * 2);

            SupportDrawnFunctions.drawnPoint(inkCanvas, _virtualCircleCenter, Colors.DarkRed);
            return _virtualCircleCenter.getDistanceToPoint(point);
        }
    }
}